package com.mask.mediaprojection.utils;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.media.projection.MediaProjectionManager;
import android.os.Environment;
import android.os.IBinder;
import android.util.DisplayMetrics;
import android.util.Log;

import com.mask.mediaprojection.interfaces.MediaProjectionNotificationEngine;
import com.mask.mediaprojection.interfaces.MediaRecorderCallback;
import com.mask.mediaprojection.interfaces.ScreenCaptureCallback;
import com.mask.mediaprojection.service.MediaProjectionService;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.channels.FileChannel;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * 媒体投影 帮助类
 * Created by lishilin on 2020/03/18
 */
public class MediaProjectionHelper {

    public static final int REQUEST_CODE = 10086;

    private static class InstanceHolder {
        private static final MediaProjectionHelper instance = new MediaProjectionHelper();
    }

    public static MediaProjectionHelper getInstance() {
        return InstanceHolder.instance;
    }

    private MediaProjectionHelper() {
        super();
    }

    private MediaProjectionNotificationEngine notificationEngine;

    private MediaProjectionManager mediaProjectionManager;
    private DisplayMetrics displayMetrics;

    private ServiceConnection serviceConnection;
    private MediaProjectionService mediaProjectionService;

    /**
     * 设置 通知引擎
     *
     * @param notificationEngine notificationEngine
     */
    public void setNotificationEngine(MediaProjectionNotificationEngine notificationEngine) {
        this.notificationEngine = notificationEngine;
    }

    /**
     * 启动媒体投影服务
     *
     * @param activity activity
     */
    public void startService(Activity activity) {
        if (mediaProjectionManager != null) {
            return;
        }

        // 启动媒体投影服务
        mediaProjectionManager = (MediaProjectionManager) activity.getSystemService(Context.MEDIA_PROJECTION_SERVICE);
        if (mediaProjectionManager != null) {
            activity.startActivityForResult(mediaProjectionManager.createScreenCaptureIntent(), REQUEST_CODE);
        }

        // 此处宽高需要获取屏幕完整宽高，否则截屏图片会有白/黑边
        displayMetrics = new DisplayMetrics();
        activity.getWindowManager().getDefaultDisplay().getRealMetrics(displayMetrics);

        // 绑定服务
        serviceConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                if (service instanceof MediaProjectionService.MediaProjectionBinder) {
                    mediaProjectionService = ((MediaProjectionService.MediaProjectionBinder) service).getService();
                    mediaProjectionService.setNotificationEngine(notificationEngine);
                }
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
                mediaProjectionService = null;
            }
        };
        MediaProjectionService.bindService(activity, serviceConnection);
    }

    /**
     * 停止媒体投影服务
     *
     * @param context context
     */
    public void stopService(Context context) {
        mediaProjectionService = null;

        if (serviceConnection != null) {
            MediaProjectionService.unbindService(context, serviceConnection);
            serviceConnection = null;
        }

        displayMetrics = null;

        mediaProjectionManager = null;
    }

    /**
     * 创建VirtualDisplay(onActivityResult中调用)
     *
     * @param requestCode           requestCode
     * @param resultCode            resultCode
     * @param data                  data
     * @param isScreenCaptureEnable 是否可以屏幕截图
     * @param isMediaRecorderEnable 是否可以媒体录制
     */
    public void createVirtualDisplay(int requestCode, int resultCode, Intent data, boolean isScreenCaptureEnable, boolean isMediaRecorderEnable) {
        if (mediaProjectionService == null) {
            return;
        }
        if (requestCode != REQUEST_CODE) {
            return;
        }
        if (resultCode != Activity.RESULT_OK) {
            return;
        }

        mediaProjectionService.createVirtualDisplay(resultCode, data, displayMetrics, isScreenCaptureEnable, isMediaRecorderEnable);
    }

    /**
     * 屏幕截图
     *
     * @param callback callback
     */
    public void capture(ScreenCaptureCallback callback) {
        if (mediaProjectionService == null) {
            callback.onFail();
            return;
        }
        mediaProjectionService.capture(callback);
    }

    /**
     * 开始 屏幕录制
     *
     * @param callback callback
     */
    public void startMediaRecorder(MediaRecorderCallback callback) {
        if (mediaProjectionService == null) {
            callback.onFail();
            return;
        }
        mediaProjectionService.startRecording(callback);

        thread = new Thread(new Runnable() {
            @Override
            public void run() {
                getFile();
            }
        });
        thread.start();

    }

    private void getFile() {
        try {
            Log.d("12323", "getFile ");
            Thread.sleep(2000);
            File file = mediaProjectionService.getMediaFile();
            String getCacheMovieDir = mediaProjectionService.getCacheMovieDir();
            // 创建保存路径
//            final File dirFile = FileUtils.getCacheMovieDir();
//            boolean mkdirs = dirFile.mkdirs();
//            // 创建保存文件
//            mediaFile = new File(dirFile, FileUtils.getDateName("MediaRecorder") + ".mp4");

            nioSpilt(file, getCacheMovieDir+"/"+FileUtils.getDateName("MediaRecorder"), 20*1024);

            getFile();
        } catch (Exception e) {
            e.printStackTrace();
            Log.d("12323", "getFile error = "+e.getLocalizedMessage());
        }
    }

    Thread thread;

    /**
     * 停止 屏幕录制
     */
    public void stopMediaRecorder() {
        if (mediaProjectionService == null) {
            return;
        }
        mediaProjectionService.stopRecording();
        thread.stop();
    }

    //file需要分片的文件，splitNum:要分几片，currentDir：分片后存放的位置，splitSize：按多大分片
    public static void nioSpilt(File file, String currentDir, long splitSize) throws Exception {
        FileInputStream fis = new FileInputStream(file);
        FileChannel inputChannel = fis.getChannel();
        FileOutputStream fos;
        FileChannel outputChannel;
        File currentDirFile = new File(currentDir);
        if (!currentDirFile.exists()){
            currentDirFile.mkdirs();
        }
        long startPoint = 0;
        long splitNum = file.length() / splitSize;

        File cac = new File(currentDir);
        cac.mkdirs();
//        long l1 = file.length() % splitSize;
//        long splitNum = l+l1
        Log.d("12323", "cac = "+currentDir);
        Log.d("12323", "splitNum = "+splitNum);
        for (int i = 1; i <= splitNum; i++) {
            String splitFileName = currentDir+"/" + i;
            File splitFile = new File(splitFileName);
            splitFile.createNewFile();
            fos = new FileOutputStream(splitFileName);
            outputChannel = fos.getChannel();
            inputChannel.transferTo(startPoint, splitSize, outputChannel);
            startPoint += splitSize;
            outputChannel.close();
            fos.close();
            Log.d("12323", "Md5 = "+splitFile.getAbsolutePath()+", -- "+fileMd5(splitFile));
        }
        inputChannel.close();
        fis.close();
    }


    private static final char[] hexCode = "0123456789ABCDEF".toCharArray();

    public String md5(String input) throws NoSuchAlgorithmException {
        byte[] bytes = MessageDigest.getInstance("MD5").digest(input.getBytes());
        return printHexBinary(bytes);
    }

    public String printHexBinary(byte[] data) {
        StringBuilder r = new StringBuilder(data.length * 2);
        for (byte b : data) {
            r.append(hexCode[(b >> 4) & 0xF]);
            r.append(hexCode[(b & 0xF)]);
        }
        return r.toString();
    }

    public static String fileMd5(File file) throws Exception {
        MessageDigest md = MessageDigest.getInstance("MD5");
//        b5302d0a64fc86dd78833ae104f90b62
//        b5302d0a64fc86dd78833ae104f90b62
        FileInputStream fis = new FileInputStream(file);

        byte[] dataBytes = new byte[1024];

        int nread = 0;
        while ((nread = fis.read(dataBytes)) != -1) {
            md.update(dataBytes, 0, nread);
        };
        byte[] mdbytes = md.digest();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < mdbytes.length; i++) {
            sb.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1));
        }
//        System.out.println("Digest(in hex format):: " + sb.toString());
        return  sb.toString();
    }


}
